/*
 * Copyright (c) 2025 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef SIGNAL_H
#define SIGNAL_H

#include <arch/context.h>
#include <stdlib/stdint.h>
#include <stdlib/stddef.h>
#include <core/ipi.h>
#include <uapi/ipcops.h>
#include <core/signal_common.h>

/**
 * @brief   calculate the position of the least significant set bit
 *
 * @param   bit_map     calculate the position of the least significant set bit
 * @return  int32_t     the position of the least significant set bit
 */
static inline int32_t ffs64_msb(uint64_t bit_map)
{
    (void)bit_map;

    return (int32_t)(MAX_SIG - SIG_CLZLL(bit_map));
}

/**
 * @brief   efficiently generate a signal mask for the specified signal number
 *
 * @param   num         the signal number
 * @return  sig_set_t   a signal mask where the bit corresponding to the signal number
 */
static inline sig_set_t sig_mask_fast(int32_t num)
{
    return (sig_set_t)(1UL << (uint64_t)(num - 1));
}

/**
 * @brief  generate a signal mask for the specified signal number with range validation
 *
 * @param   num         the signal number
 * @return  sig_set_t   a signal mask where the bit corresponding to the signal number
 */
static inline sig_set_t sig_mask(int32_t num)
{
    if ((num < MIN_SIG) || (num > MAX_SIG)) {
        return (sig_set_t)0UL;
    } else {
        return (sig_set_t)(1UL << (uint64_t)(num - 1));
    }
}

void sig_timeout_wake(tcb_t *tid);
void sig_kill(tcb_t *tid, int32_t sig_num);
void sig_check_and_handle(void);
void sig_proc_mask(int32_t how, const sig_set_t *set, sig_set_t *old_set);
void sig_handle(uint64_t cmd, op_signal_param_t *cfg);
#ifdef CONFIG_ENABLE_SMP
void ipi_signal_handler(ipi_data_t *data);
#endif
#endif
